package MultiChat;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;


public class ChatThread implements Runnable {
	private Socket socket = null;
	private final int id;
	private String login;
	private ChatServer chatServer = null;
	
	public ChatThread(ChatServer chatServer, Socket socket, int id) {
		this.socket = socket;
		this.id = id;
		this.chatServer = chatServer;
	}

	public Socket getSocket() {
		return this.socket;
	}
	

	public String getLogin() {
		return this.login;
	}
	
	@Override
	public void run() {
		BufferedReader threadReader = null;
		PrintWriter threadWriter = null;
		PrintWriter writer = null;

		try {
			threadReader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
			threadWriter = new PrintWriter(this.socket.getOutputStream());

			//[ek] TODO try to refactor to if(_NOT_ checkAuth) then _some error_ form - it's more readable
			if (checkAuth(threadReader, threadWriter)) {
				threadWriter.println("server > Hi, " + this.login);
				threadWriter.flush();
				
				while (true) {
					//while (threadReader.ready()) {
					Message message = new Message(threadReader); //[ek] XXX a very, VERY lot of new Message. You'll kill the GC.
					
					chatServer.log(this.login + " > " + message);
					
					// [DF] FIXME: �������� ������������� �����������  ChatServer.connections � ��� ������. �����������������.
					
					if (message.getTo().equals("all")) {
						for ( ChatThread connection : ChatServer.connections ) {
							Socket s = connection.getSocket();
							
							if (s != null && !s.isClosed()) {
								writer = new PrintWriter(s.getOutputStream()); //[ek] XXX maybe cache it? 
								new Message(message.getTo(), this.login + " > " + message.getText()).sendMessage(writer);
							} //[ek] TODO and what else?
						}
					} else {
						//[ek] TODO reuse dublicate logic
						for ( ChatThread connection : ChatServer.connections ) {
							Socket s = connection.getSocket();
							
							if (s != null && !s.isClosed() && message.getTo().equals(connection.getLogin())) {
								writer = new PrintWriter(s.getOutputStream());
								new Message(message.getTo(), this.login + " > " + message.getText()).sendMessage(writer);
								break; //[ek] TODO why?
							}
						}
					}
					//}
					
					//Thread.sleep(100);
				}
			}
			
		}
//		catch (InterruptedException e) {
//			e.printStackTrace();
//		}
		catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (this.socket != null) {
				try {
					this.socket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	private boolean checkAuth(BufferedReader threadReader, PrintWriter threadWriter) {
		boolean ret = false;
		while (!ret) {
			try {
				boolean waiting = true;
				String login = null;
				String password = null;
				
				threadWriter.println("server > Enter login");
				threadWriter.flush();
				
				login = threadReader.readLine();
				
				threadWriter.println("server > Enter password");
				threadWriter.flush();

				password = threadReader.readLine();
				
				if (login.equals(password)) { //[ek] TODO WTF?
					ret = true;
					this.login = login;
					for ( ChatThread connection : ChatServer.connections ) {
						Socket s = connection.getSocket();
						if (s != null && !s.isClosed()) {
							PrintWriter writer = new PrintWriter(s.getOutputStream());;
							writer.println("server > " + this.login + " joined chat");
							writer.flush();
						}
					}
					//ChatServer.sockets.add(socket);
					ChatServer.connections.add(this);
				} else {
					threadWriter.println("server > wrong login-password entered. retype");
					threadWriter.flush();
				}
			} catch (IOException e) {
				e.printStackTrace(); //[ek] TODO will user know about error?
			}
		}

		return ret;
	}
}
